/*
 * DinnerRestController.java
 * Copyright (c) 2014, 2019, Kiri. 
 * All rights reserved.
 */
package com.onesalt.web.api;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.onesalt.common.ExceptionConstants;
import com.onesalt.domain.Dinner;
import com.onesalt.domain.Kitchen;
import com.onesalt.domain.Order;
import com.onesalt.domain.User;
import com.onesalt.service.DinnerService;
import com.onesalt.service.KitchenService;
import com.onesalt.service.OrderService;
import com.onesalt.web.api.request.AddDinnersRequest;
import com.onesalt.web.api.response.DinnerListRespone;
import com.onesalt.web.api.response.DinnerResponse;
import com.onesalt.web.api.response.Response;

/**
 * 
 *
 * @author kiri
 * @date 2015年5月9日
 * @version 1.0
 */
@RestController
@RequestMapping("/api/dinners")
public class DinnerRestController extends AbstractRestController {

	@Autowired
	private DinnerService dinnerService;

	@Autowired
	private KitchenService kitchenService;

	@Autowired
	private OrderService orderService;

	@RequestMapping(value = "/findSelect", method = RequestMethod.GET)
	public DinnerListRespone findSelect(@RequestParam int page, @RequestParam int size) {
		Page<Dinner> dinners = dinnerService.getDinnerRepository().findAllValidPagable(new Date(), Dinner.STATUS_CANCELLED,
				new PageRequest(page, size, Direction.DESC, "createTime"));
		DinnerListRespone response = new DinnerListRespone();
		setDinners(response, dinners.getContent());
		response.setPage(dinners.getNumber());
		response.setLast(dinners.isLast());
		return response;
	}

	@RequestMapping(value = "/findValid", method = RequestMethod.GET)
	public DinnerListRespone findValid(@RequestParam Long kitchenId, @RequestParam(defaultValue = "0", required = false) int page,
			@RequestParam(defaultValue = "20", required = false) int size) {
		Kitchen kitchen = kitchenService.getKitchenRepository().findOne(kitchenId);
		if (kitchen == null) {
			throw ExceptionConstants.KITCHEN_NOT_EXISTS_EXCEPTION;
		}

		Page<Dinner> dinners = dinnerService.getDinnerRepository().findValidPagable(kitchenId, new Date(), Dinner.STATUS_CANCELLED,
				new PageRequest(page, size, new Sort(Direction.ASC, "startTime")));
		DinnerListRespone response = new DinnerListRespone();

		setDinners(response, dinners.getContent());
		response.setPage(dinners.getNumber());
		response.setLast(dinners.isLast());
		return response;
	}

	@RequestMapping(value = "/findHistory", method = RequestMethod.GET)
	public DinnerListRespone findHistory(@RequestParam Long kitchenId, @RequestParam(defaultValue = "0", required = false) int page,
			@RequestParam(defaultValue = "20", required = false) int size) {
		Kitchen kitchen = kitchenService.getKitchenRepository().findOne(kitchenId);
		if (kitchen == null) {
			throw ExceptionConstants.KITCHEN_NOT_EXISTS_EXCEPTION;
		}

		Page<Dinner> dinners = dinnerService.getDinnerRepository().findHistoryPagable(kitchenId, new Date(), Dinner.STATUS_CANCELLED,
				new PageRequest(page, size, new Sort(Direction.DESC, "startTime")));
		DinnerListRespone response = new DinnerListRespone();

		setDinners(response, dinners.getContent());
		response.setPage(dinners.getNumber());
		response.setLast(dinners.isLast());
		return response;
	}

	@RequestMapping(value = "/findByStartTime", method = RequestMethod.GET)
	public DinnerListRespone findByStartTime(@RequestParam Long kitchenId, @RequestParam Long startTime, @RequestParam Long endTime) {
		Kitchen kitchen = kitchenService.getKitchenRepository().findOne(kitchenId);
		if (kitchen == null) {
			throw ExceptionConstants.KITCHEN_NOT_EXISTS_EXCEPTION;
		}

		List<Dinner> dinners = dinnerService.getDinnerRepository().findByKitchenIdAndStartTimeBetween(kitchenId, new Date(startTime),
				new Date(endTime));
		DinnerListRespone response = new DinnerListRespone();
		setDinners(response, dinners);
		return response;
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
	public DinnerListRespone addDinners(@RequestBody AddDinnersRequest request) {
		Kitchen kitchen = kitchenService.getKitchenRepository().findOne(request.getKitchenId());
		if (kitchen == null) {
			throw ExceptionConstants.KITCHEN_NOT_EXISTS_EXCEPTION;
		}

		List<Dinner> dinners = dinnerService.createDinners(kitchen, request.getDinners());
		DinnerListRespone response = new DinnerListRespone();
		response.setDinners(dinners);
		return response;
	}

	@RequestMapping(value = "/detail", method = RequestMethod.GET)
	public DinnerResponse getDetail(@RequestParam Long dinnerId) {
		Dinner dinner = dinnerService.getDinnerRepository().findOne(dinnerId);
		if (dinner == null) {
			throw ExceptionConstants.DINNER_NOT_EXISTS_EXCEPTION;
		}
		Kitchen kitchen = kitchenService.getKitchenRepository().findOne(dinner.getKitchenId());
		User cook = getUserService().getUserRepository().findOne(kitchen.getCookId());

		List<Order> orders = orderService.getOrderRepository().findByDinnerIdOrderByCreateTimeDesc(dinnerId);
		for (Order order : orders) {
			order.setDiner(getUserService().getUserRepository().findOne(order.getDinerId()));
		}
		DinnerResponse response = new DinnerResponse();
		response.setCook(cook);
		response.setDinner(dinner);
		response.setKitchen(kitchen);
		response.setOrders(orders);
		return response;
	}

	@RequestMapping(value = "/cancel", method = RequestMethod.POST)
	public Response cancelDinner(@RequestParam Long dinnerId) {
		dinnerService.cancelDinner(dinnerId);
		return Response.SUCCESS;
	}

	public void setDinners(DinnerListRespone response, List<Dinner> dinners) {
		List<Kitchen> kitchens = new ArrayList<Kitchen>();
		Set<Long> kitchenIds = new HashSet<Long>();
		for (Dinner dinner : dinners) {
			Long kitchenId = dinner.getKitchenId();
			if (kitchenId != null && !kitchenIds.contains(kitchenId)) {
				Kitchen kitchen = kitchenService.getKitchenRepository().findOne(kitchenId);
				if (kitchen != null) {
					kitchen.setCook(getUserService().getUserRepository().findOne(kitchen.getCookId()));
					kitchens.add(kitchen);
					getLogger().debug("kitchen = " + kitchenId + ", dishes = " + kitchen.getDishes());
				}
				kitchenIds.add(kitchenId);
			}
			getLogger().debug("dinner = " + dinner.getDinnerId() + ", dishes = " + dinner.getDishes());
		}
		response.setDinners(dinners);
		response.setKitchens(kitchens);
	}
}
